#ifndef SEMANTICNODEBLOCKIF_H_
#define SEMANTICNODEBLOCKIF_H_

#include "SemanticNode.h"
#include "SemanticNodeBlockGenerate.h"
#include "SemanticNodeBlockTerminate.h"
#include "SemanticNodeBlockAdvance.h"
#include "SemanticNodeBlockEnter.h"
#include "SemanticNodeBlockLeave.h"
#include "SemanticNodeBlockSeize.h"
#include "SemanticNodeBlockRelease.h"
#include "SemanticNodeBlockInqueue.h"
#include "SemanticNodeBlockOutqueue.h"
#include "SemanticNodeBlockArrive.h"
#include "SemanticNodeBlockDepart.h"
#include "SemanticNodeBlockModelInstance.h"
#include "SemanticNodeBlockGoto.h"
//#include "SemanticNodeBlockWait.h"
#include "SemanticNodeBlockJoinGroup.h"
#include "SemanticNodeBlockLeaveGroup.h"
#include "SemanticNodeBlockCreate.h"
#include "SemanticNodeBlockSplit.h"
#include "SemanticNodeBlockGather.h"
#include "SemanticNodeBlockExecute.h"
#include "LabeledNode.h"
#include <string>
#include <vector>

class SemanticNodeExpression;
class SemanticNodeBlockWait;

class SemanticNodeBlockIf : public SemanticNode, public LabeledNode {
private:
	SemanticNodeExpression *expression;

	/** GPSS blokovi. */
	std::vector<SemanticNodeBlockGenerate *> generators;
	std::vector<SemanticNodeBlockTerminate *> terminators;
	std::vector<SemanticNodeBlockAdvance *> advancers;
	std::vector<SemanticNodeBlockEnter *> entrants;
	std::vector<SemanticNodeBlockLeave *> leavers;
	std::vector<SemanticNodeBlockSeize *> seizers;
	std::vector<SemanticNodeBlockRelease *> releasers;
	std::vector<SemanticNodeBlockInqueue *> inqueuers;
	std::vector<SemanticNodeBlockOutqueue *> outqueuers;
	std::vector<SemanticNodeBlockArrive *> arrivals;
	std::vector<SemanticNodeBlockDepart *> departures;
	std::vector<SemanticNodeBlockModelInstance *> modelInstances;
	std::vector<SemanticNodeBlockGoto *> gotos;
	std::vector<SemanticNodeBlockIf *> ifs;
	std::vector<SemanticNodeBlockWait *> waiters;
	std::vector<SemanticNodeBlockJoinGroup *> groupJoiners;
	std::vector<SemanticNodeBlockLeaveGroup *> groupLeavers;
	std::vector<SemanticNodeBlockCreate *> creators;
	std::vector<SemanticNodeBlockSplit *> splitters;
	std::vector<SemanticNodeBlockGather *> gatherers;
	std::vector<SemanticNodeBlockExecute *> executors;

	bool elseStructure;

	/** Poredak GPSS blokova. */
	std::vector<SemanticNode *> thenStructureNodeOrder;
	std::vector<SemanticNode *> elseStructureNodeOrder;

public:
	SemanticNodeBlockIf(const SyntaxTreeNode *ifNodeParent, SemanticNode *parent);

	bool hasElse();

	void addBlockTerminate(SemanticNodeBlockTerminate *terminator, bool which = false);
	void addBlockGenerate(SemanticNodeBlockGenerate *generator, bool which = false);
	void addBlockAdvance(SemanticNodeBlockAdvance *advancer, bool which = false);
	void addBlockEnter(SemanticNodeBlockEnter *entrant, bool which = false);
	void addBlockLeave(SemanticNodeBlockLeave *leaver, bool which = false);
	void addBlockSeize(SemanticNodeBlockSeize *seizer, bool which = false);
	void addBlockRelease(SemanticNodeBlockRelease *releaser, bool which = false);
	void addBlockInqueue(SemanticNodeBlockInqueue *inqueuer, bool which = false);
	void addBlockOutqueue(SemanticNodeBlockOutqueue *outqueuer, bool which = false);
	void addBlockArrive(SemanticNodeBlockArrive *arrivee, bool which = false);
	void addBlockDepart(SemanticNodeBlockDepart *departure, bool which = false);
	void addBlockModelInstance(SemanticNodeBlockModelInstance *modelInstance, bool which = false);
	void addBlockGoto(SemanticNodeBlockGoto *gotoer, bool which = false);
	void addBlockIf(SemanticNodeBlockIf *ifer, bool which = false);
	void addBlockWait(SemanticNodeBlockWait *waiter, bool which = false);
	void addBlockJoinGroup(SemanticNodeBlockJoinGroup *groupJoiner, bool which = false);
	void addBlockLeaveGroup(SemanticNodeBlockLeaveGroup *groupLeaver, bool which = false);
	void addBlockCreate(SemanticNodeBlockCreate *creator, bool which = false);
	void addBlockSplit(SemanticNodeBlockSplit *splitter, bool which = false);
	void addBlockGather(SemanticNodeBlockGather *gatherer, bool which = false);
	void addBlockExecute(SemanticNodeBlockExecute *executor, bool which = false);

	void setExpression(SemanticNodeExpression *expr);

	virtual std::string toDebugString(int tab);
};

#endif /* SEMANTICNODEBLOCKIF_H_ */